package org.game.manager;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolError;
import com.xiaoleilu.hutool.date.DateUtil;
import org.cfg.MonthCardCfg;
import org.cfg.RechargeCfg;
import org.cfg.RechargeGiftBagCfg;
import org.cfg.cache.MonthCardCfgCache;
import org.cfg.cache.RechargeCfgCache;
import org.cfg.cache.RechargeGiftBagCfgCache;
import org.constant.*;
import org.error.GameErrorCode;
import org.game.db.bean.*;
import org.game.db.cache.MonthCardCache;
import org.game.db.cache.RechargeOrderCache;
import org.game.db.cache.PlayerCache;
import org.game.db.cache.RechargeGiftBagRecordCache;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.module.itembo.ItemBO;
import org.game.module.rechargebo.RechargeBO;
import org.game.msgBuilder.RechargeMsgBuilder;
import org.game.plugin.event.GameEvent;
import org.game.plugin.event.GameEventPlugin;
import org.game.protobuf.s2c.S2CItemMsg;
import org.game.protobuf.s2c.S2CShareMsg;
import org.game.util.ProtoUnit;
import org.utils.TimeUtil;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 游戏服充值管理器
 * Created by fxf on 2018-2-9.
 */
public class GameRechargeManager {

    private GameRechargeManager() {
    }

    /**
     * 交付订单商品
     *
     * @param playerId        玩家id
     * @param orderId         订单id
     * @param rechargeGoodsId 充值商品id
     */
    public static boolean deliveryOrderGoods(int playerId, String orderId, int rechargeGoodsId) {
        RechargeOrder rechargeOrder = RechargeOrderCache.me().getById(orderId);
        ToolError.isAndTrue(GameErrorCode.ORDER_DELIVERED, "订单已经交付", rechargeOrder != null);
        rechargeOrder = new RechargeOrder(orderId, rechargeGoodsId, playerId);
        rechargeOrder.insert();

        RechargeCfg cfg = RechargeCfgCache.me().getById(rechargeOrder.getGoodsId());
        Player player = PlayerCache.me().getById(playerId);
        if (cfg.getType() == RechargeConstant.RECHARGE_GOODS_TYPE_MONTH_CARD) {
            deliveryMonthCard(player, cfg);
        } else if (cfg.getType() == RechargeConstant.RECHARGE_GOODS_TYPE_GIFT_BAG) {
            deliveryRechargeGiftBag(player, cfg);
        }
        player.getPlayerProxy().sendMsg(RechargeBO.rechargeSuccess, RechargeMsgBuilder.buildRechargeSuccessMsg(cfg.getId()));
        return true;
    }


    /**
     * 限购检查
     */
    public static void checkPurchaseLimitation(Player player, RechargeCfg rechargeCfg) {
        if (rechargeCfg.getType() == RechargeConstant.RECHARGE_GOODS_TYPE_MONTH_CARD) {
            MonthCard mc = player.getMonthCardsFkPlayerId();
            MonthCardCfg cardCfg = MonthCardCfgCache.me().getById(rechargeCfg.getGoodsId());
            if (mc != null) {
                RechargeCfg nowRechargeCfg = RechargeCfgCache.me().getById(mc.getCid());
                MonthCardCfg nowMonthCardCfg = MonthCardCfgCache.me().getById(nowRechargeCfg.getGoodsId());
                ToolError.isAndTrue(GameErrorCode.NOT_CONFORM_TO_THE_RULES, "", nowMonthCardCfg.getUpgradeId() != cardCfg.getId());
            } else {
                ToolError.isAndTrue(GameErrorCode.BUY_MONTH_CARD_FIRST_PLEASE, "请先购买月卡", cardCfg.getType() != RechargeConstant.CARD_TYPE_MONTH_CARD);
            }
        } else {

            RechargeGiftBagCfg giftBagCfg = RechargeGiftBagCfgCache.me().getById(rechargeCfg.getGoodsId());

            //1.等级校验
            int[] levelLimit = giftBagCfg.getPlayerLevel();
            if (levelLimit != null && levelLimit.length > 0) {
                ToolError.isAndTrue(GameErrorCode.PLAYER_LEVEL_ERR, "等级不足或超过，不能购买", player.getLevel() > levelLimit[0] || player.getLevel() < levelLimit[1]);
            }

            //2.校验购买限制时间
            Calendar startTime = null;
            if (giftBagCfg.getStartDate() != null && giftBagCfg.getStartDate().length > 0) {
                startTime = TimeUtil.getAssignCalendar(giftBagCfg.getStartDate());
            }
            Calendar endTime = null;
            if (giftBagCfg.getEndDate() != null && giftBagCfg.getEndDate().length > 0) {
                endTime = TimeUtil.getAssignCalendar(giftBagCfg.getEndDate());
            }
            long now = System.currentTimeMillis();
            ToolError.isAndTrue(GameErrorCode.BEFORE_THE_START_TIME, "还未到开始售卖时间", startTime != null && now < startTime.getTimeInMillis());
            ToolError.isAndTrue(GameErrorCode.MORE_THAN_END_TIME, "售卖时间已经结束", endTime != null && now > endTime.getTimeInMillis());

            //3.校验购买次数,配置购买次数为0则不限购
            if (giftBagCfg.getBuyCount() != 0) {
                RechargeGiftBagRecord record = RechargeGiftBagRecordCache.me().getRechargeGiftBagRecordCacheProxy().getByPlayerIdCid(player.getId(), giftBagCfg.getId());
                if (record != null) {
                    ToolError.isAndTrue(GameErrorCode.BUY_COUNT_BEYOND_UPPER_LIMIT, "已达购买次数上限", record.getBuyCount() >= giftBagCfg.getBuyCount());
                }
            }
        }
    }

    /**
     * 重置充值礼包购买记录
     */
    public static void resetGiftBagRecord(Player player) {
        List<RechargeGiftBagRecord> recordList = player.getRechargeGiftBagRecordsFkPlayerId();
        List<RechargeGiftBagRecord> updateList = Lists.newArrayList();
        recordList.forEach(record -> {
            RechargeGiftBagCfg cfg = RechargeGiftBagCfgCache.me().getById(record.getCid());
            switch (cfg.getResetType()) {
                case RechargeConstant.RESET_TYPE_DAILY: {
                    record.getRechargeGiftBagRecordProxy().reset();
                    updateList.add(record);
                    break;
                }
                case RechargeConstant.RESET_TYPE_WEEK: {
                    Calendar c = Calendar.getInstance();
                    int resetDate = cfg.getResetDate() == 0 ? Calendar.MONDAY : cfg.getResetDate();
                    if (c.get(Calendar.DAY_OF_WEEK) == resetDate) {
                        record.getRechargeGiftBagRecordProxy().reset();
                        updateList.add(record);
                    }
                    break;
                }
                case RechargeConstant.RESET_TYPE_MONTH: {
                    Calendar c = Calendar.getInstance();
                    int resetDate = cfg.getResetDate() == 0 ? 1 : cfg.getResetDate();
                    if (c.get(Calendar.DAY_OF_MONTH) == resetDate) {
                        record.getRechargeGiftBagRecordProxy().reset();
                        updateList.add(record);
                    }
                    break;
                }
            }
        });
        if (updateList.size() > 0) {
            player.getPlayerProxy().sendMsg(RechargeBO.getBuyRecordInfo, RechargeMsgBuilder.buildGetBuyRecordInfoMsg(updateList, S2CShareMsg.ChangeType.UPDATE));
        }
    }


    /**
     * 交付订单商品 测试用！！
     *
     * @param playerId        玩家id
     * @param orderId         订单id
     * @param rechargeGoodsId 充值商品id
     */
    public static boolean testDeliveryOrderGoods(int playerId, String orderId, int rechargeGoodsId) {
        RechargeOrder rechargeOrder = RechargeOrderCache.me().getById(orderId);
        ToolError.isAndTrue(GameErrorCode.ORDER_DELIVERED, "订单已经交付", rechargeOrder != null);
        rechargeOrder = new RechargeOrder(orderId, rechargeGoodsId, playerId);
        rechargeOrder.insert();
        System.out.println();//仅为消除重复提示

        RechargeCfg cfg = RechargeCfgCache.me().getById(rechargeOrder.getGoodsId());
        Player player = PlayerCache.me().getById(playerId);
        if (cfg.getType() == RechargeConstant.RECHARGE_GOODS_TYPE_MONTH_CARD) {
            deliveryMonthCard(player, cfg);
        } else if (cfg.getType() == RechargeConstant.RECHARGE_GOODS_TYPE_GIFT_BAG) {
            deliveryRechargeGiftBag(player, cfg);
        }
        player.getPlayerProxy().sendMsg(RechargeBO.rechargeSuccess, RechargeMsgBuilder.buildRechargeSuccessMsg(cfg.getId()));
        return true;
    }

    // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓private method↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

    /**
     * 交付月卡delivery
     */
    private static void deliveryMonthCard(Player player, RechargeCfg cfg) {
        MonthCardCfg monthCardCfg = MonthCardCfgCache.me().getById(cfg.getGoodsId());
        MonthCard mc = MonthCardCache.me().getByPlayerId(player.getId());
        recordRecharge(player,cfg);
        S2CShareMsg.ChangeType ct = S2CShareMsg.ChangeType.UPDATE;
        if (mc == null) {
            mc = new MonthCard(0l, cfg.getId(), null, null, player.getId());
            mc.insert();
            ct = S2CShareMsg.ChangeType.ADD;
        }

        Calendar c = DateUtil.beginOfDay(Calendar.getInstance());
        c.add(Calendar.DATE, monthCardCfg.getDays());
        mc.setGainLimitDate(c.getTime());
        mc.setCid(cfg.getId());
        mc.update();


        S2CItemMsg.ItemList.Builder itemChange = S2CItemMsg.ItemList.newBuilder();
        if (monthCardCfg.getPresentItem() != null) {
            ItemManager.addGoods(player, null, null, itemChange, LogDsp.newBuilder(GoodsDsp.MONTH_CARD_PRESENT), monthCardCfg.getPresentItem());
        }
        player.getPlayerProxy().sendMsg(RechargeBO.sendBuyMonthCardInfo, RechargeMsgBuilder.buildBuyMonthCardInfoMsg(mc, itemChange.build(), ct));
        player.getPlayerProxy().sendMsg(MessageManager.me().create(ItemBO.getItems, ProtoUnit.toByte(itemChange.build())));

        // 触发任务激活事件
        Map<String, Object> in = Maps.newHashMap();
        in.put(EventConditionKey.CONDITION_TYPE, EventConditionType.GAIN_MONTH_CARD);
        GameEvent event = new GameEvent(player, EventType.OTHER_EVENT, in);
        GameEventPlugin.syncSubmit(event);
    }

    /**
     * 交付礼包
     */
    private static void deliveryRechargeGiftBag(Player player, RechargeCfg cfg) {
        RechargeGiftBagCfg giftBagCfg = RechargeGiftBagCfgCache.me().getById(cfg.getGoodsId());
        recordRecharge(player, cfg);
        boolean isFirstRecharge = firstRecharge(player,cfg,giftBagCfg);
        if (!isFirstRecharge){
            ItemManager.addGoodsAndPush(player, null, null, giftBagCfg.getItem(), LogDsp.newBuilder(GoodsDsp.RECHARGE).addAttr("rechargeId", cfg.getId()));
        }
    }

    /**
     * 记录重置
     *
     * @param player 玩家
     * @param cfg    rechargeCfg
     */
    private static void recordRecharge(Player player, RechargeCfg cfg) {
        S2CShareMsg.ChangeType ct = S2CShareMsg.ChangeType.UPDATE;
        RechargeGiftBagRecord record = RechargeGiftBagRecordCache.me().getRechargeGiftBagRecordCacheProxy().getByPlayerIdCid(player.getId(), cfg.getId());
        if (record == null) {
            record = new RechargeGiftBagRecord(0l, player.getId(), cfg.getId(), new Date(), 1, new Date(), 1);
            record.insert();
            ct = S2CShareMsg.ChangeType.ADD;
        } else {
            record.setBuyCount(record.getBuyCount() + 1);
            record.setTotalBuyCount(record.getTotalBuyCount() + 1);
            record.update();
        }
        player.getPlayerProxy().sendMsg(RechargeBO.sendBuyRecordInfo, RechargeMsgBuilder.buildBuyRecordInfo(record, ct));
    }

    /**
     * 首充 ，首充返回true，否则false
     * 领取条件：
     * 1.首冲
     * 2.有首冲奖励
     *
     * @param player      玩家
     * @param rechargeCfg 充值配置
     * @param giftBagCfg  充值礼包配置
     */
    private static boolean firstRecharge(Player player, RechargeCfg rechargeCfg, RechargeGiftBagCfg giftBagCfg) {
        if (giftBagCfg.getFirstBuyItem() != null && giftBagCfg.getFirstBuyItem().size() > 0) {
            List<RechargeOrder> rechargeOrderList = RechargeOrderCache.me().getRechargeOrderCacheProxy().getOrderListByPlayerIdGoodsId(player.getId(), rechargeCfg.getId());
            if (rechargeOrderList.size() == 1) {
                ItemManager.addGoodsAndPush(player, null, null, giftBagCfg.getFirstBuyItem(), LogDsp.newBuilder(GoodsDsp.RECHARGE).addAttr("giftBagId", giftBagCfg.getId()));
                return true;
            }
        }
        return false;
    }


}
